// 参考：https://blog.csdn.net/qq_61375542/article/details/138994084
#ifndef __RC522_H__
#define __RC522_H__

#include "main.h"

// 寄存器
// PAGE 0: 命令和状态寄存器组
#define RC522_REG_PageReg0              0x00    // 页选择寄存器
#define RC522_REG_CommandReg            0x01    // 掉电和命令寄存器
#define RC522_REG_ComIEnReg             0x02    // 中断请求控制寄存器
#define RC522_REG_DivlEnReg             0x03    // 中断请求控制寄存器
#define RC522_REG_ComIrqReg             0x04    // 中断请求位寄存器
#define RC522_REG_DivIrqReg             0x05    // 中断请求位寄存
#define RC522_REG_ErrorReg              0x06    // 指令执行的错误状态寄存器
#define RC522_REG_Status1Reg            0x07    // 通信状态寄存器
#define RC522_REG_Status2Reg            0x08    // 接收器和发送器状态寄存器
#define RC522_REG_FIFODataReg           0x09    // 64 字节 FIFO 缓冲器
#define RC522_REG_FIFOLevelReg          0x0A    // FIFO 缓冲器已存储字节的数量寄存器
#define RC522_REG_WaterLevelReg         0x0B    // FIFO 缓冲器溢出和空警告寄存器
#define RC522_REG_ControlReg            0x0C    // 其它项控制寄存器
#define RC522_REG_BitFramingReg         0x0D    // 面向位的帧的调节寄存器
#define RC522_REG_CollReg               0x0E    // 检查产生位冲突的第一个位的地址
#define RC522_REG_RFU                   0x0F    // 保留
// PAGE 1: 命令寄存器组
#define RC522_REG_PageReg1              0x10    // 页选择寄存器
#define RC522_REG_ModeReg               0x11    // 定义发送和接收通用模式的寄存器
#define RC522_REG_TxModeReg             0x12    // 定义发送过程的数据传输速率和结构的寄存器
#define RC522_REG_RxModeReg             0x13    // 定义接收过程中的数据传输速率和结构的寄存器
#define RC522_REG_TxControlReg          0x14    // 控制天线驱动器管脚 TX1 和 TX2 的寄存器
#define RC522_REG_TxAutoReg             0x15    // 控制天线驱动器设置的寄存器
#define RC522_REG_TxSelReg              0x16    // 选择天线驱动器的内部信号源的寄存器
#define RC522_REG_RxSelReg              0x17    // 选择内部接收器的设置的寄存器
#define RC522_REG_RxThresholdReg        0x18    // 选择位解码器的阈值的寄存器
#define RC522_REG_DemodReg              0x19    // 定义解调器的设置的寄存器
#define RC522_REG_RFU1A                 0x1A    // 定义接收数据包的有效长度范围的寄存器
#define RC522_REG_RFU1B                 0x1B    // 定义接收数据包的有效长度范围的寄存器
#define RC522_REG_MifareReg             0x1C    // 控制 ISO/IEC 14443A 和NFC目标模式在106kbit 速率下的通信的寄存器
#define RC522_REG_ManualRCVReg          0x1D    // 允许手动细调内部接收器的寄存器
#define RC522_REG_TypeBReg              0x1E    // 配置 ISO/IEC 14443B 的寄存器
#define RC522_REG_SerialSpeedReg        0x1F    // 选择串行 UART 接口的速率寄存器
// PAGE 2: 配置寄存器组
#define RC522_REG_PageReg2              0x20    // 页选择寄存器
#define RC522_REG_CRCResultRegM         0x21    // 显示 CRC 计算的 MSB
#define RC522_REG_CRCResultRegL         0x22    // 显示 CRC 计算的 LSB
#define RC522_REG_GsNOffReg             0x23    // 驱动器关闭时,天线驱动管脚 TX1 和 TX2 上用于调制的电导寄存器
#define RC522_REG_ModWidthReg           0x24    // 控制调制宽度的设置寄存器
#define RC522_REG_TxBitPhaseReg         0x25    // 调整 106kbit 速率下 TX 位的相位寄存器
#define RC522_REG_RFCfgReg              0x26    // 配置接收器增益和 RF 电压的寄存器
#define RC522_REG_GsNReg                0x27    // 驱动器打开时,天线驱动管脚 TX1 和 TX2 上用于调制的电导寄存器
#define RC522_REG_CWGsCfgReg            0x28    // 在无调制期间,天线驱动管脚 TX1 和 TX2 上用于调制的电导寄存器
#define RC522_REG_ModGsCfgReg           0x29    // 在调制期间,天线驱动管脚 TX1 和 TX2 上用于调制的电导寄存器
#define RC522_REG_TModeReg              0x2A    // 内部定时器的设置寄存器
#define RC522_REG_TPrescalerReg         0x2B    // 内部定时器的设置寄存器
#define RC522_REG_TReloadRegH           0x2C    // 定义 16位定时器的重载值寄存器
#define RC522_REG_TReloadRegL           0x2D    // 定义 16位定时器的重载值寄存器
#define RC522_REG_TCounterValueRegH     0x2E    // 16 位定时器的计数值寄存器
#define RC522_REG_TCounterValueRegL     0x2F    // 16 位定时器的计数值寄存器
// PAGE 3: 测试寄存器组
#define RC522_REG_PageReg3              0x30    // 页选择寄存器
#define RC522_REG_TestSel1Reg           0x31    // 通用测试信号配置寄存器
#define RC522_REG_TestSel2Reg           0x32    // 通用测试信号的配置和 PRBS 控制寄存器
#define RC522_REG_TestPinEnReg          0x33    // 使能 DO-D7 的输出驱动器(注:仅用于串行接口)
#define RC522_REG_TestPinValueReg       0x34    // 定义管脚 DO-D7 用作 1/0 总线时的值
#define RC522_REG_TestBusReg            0x35    // 内部测试总线的状态寄存器
#define RC522_REG_AutoTestReg           0x36    // 数字自检寄存器
#define RC522_REG_VersionReg            0x37    // 软件版本寄存器
#define RC522_REG_AnalogTestReg         0x38    // 管脚 AUX1 和 AUX2 输出寄存器
#define RC522_REG_TestDAC1Reg           0x39    // TestDAC1 的测试值寄存器
#define RC522_REG_TestDAC2Reg           0x3A    // TestDAC2 的测试值寄存器
#define RC522_REG_TestADCReg            0x3B    // ADC 中 I 和 Q 通道寄存器
#define RC522_REG_RFU3C                 0x3C    // 保留留用于产品测试
#define RC522_REG_RFU3D                 0x3D    // 保留留用于产品测试
#define RC522_REG_RFU3E                 0x3E    // 保留留用于产品测试
#define RC522_REG_RFU3F		  		    0x3F    // 保留留用于产品测试

// RC522 命令
#define RC522_CMD_Idle                  0x00    // 取消当前命令
#define RC522_CMD_Config                0x01    // 用于配置 FeliCa 和 NFCIP-1 通信
#define RC522_CMD_RandomID              0x02    // 产生一个10字节的随机 ID 数据
#define RC522_CMD_CalcCRC               0x03    // 启动 CRC 协处理器
#define RC522_CMD_Transmit              0x04    // 发送 FIFO 缓冲器的数据
#define RC522_CMD_NoCmdChange           0x07    // 不中断正在执行的指令,用来修改 Command Reg 寄存器中不影响命令执行的一些位,例如 PowerDown 位
#define RC522_CMD_Receive               0x08    // 启动接收器电路
#define RC522_CMD_Transceive            0x0C    // 发送 FIFO 缓冲器中的数据到天线并在发送后自动启动接收器
#define RC522_CMD_AutoColl              0x0D    // 处理 Felica 轮询(仅卡工作模式)和 ISO/IEC 14443A 防冲突(仅卡工作模式)
#define RC522_CMD_Authent               0x0E    // 验证密钥
#define RC522_CMD_SoftReset             0x0F    // 软复位

// 卡片命令
#define CARD_REQIDL                     0x26    // 寻天线区内未进入休眠状态
#define CARD_REQALL                     0x52    // 寻天线区内全部卡
#define CARD_ANTICOLL1                  0x93    // 防冲撞
#define CARD_ANTICOLL2                  0x95    // 防冲撞
#define CARD_AUTHENT1A                  0x60    // 验证A密钥
#define CARD_AUTHENT1B                  0x61    // 验证B密钥
#define CARD_READ                       0x30    // 读块
#define CARD_WRITE                      0xA0    // 写块
#define CARD_DECREMENT                  0xC0    // 扣款
#define CARD_INCREMENT                  0xC1    // 充值
#define CARD_RESTORE                    0xC2    // 调块数据到缓冲区
#define CARD_TRANSFER                   0xB0    // 保存缓冲区中数据
#define CARD_HALT                       0x50    // 休眠

// 错误码
#define RC522_ERR_OK                    0x00    // 无错误
#define RC522_ERR_ERR                   0x01    // 错误
#define RC522_ERR_NOCARD                0x02    // 无卡片
#define RC522_ERR_PASSWORD              0x03    // 密码错误

#define RC522_REC_MAXLEN                18

#define KORO_OK                         0
#define KORO_ERR                        1
#define KORO_NOCARD                     2
#define KORO_NOTKORO                    3

struct rc522Stu {
    SPI_HandleTypeDef *hspi;

    GPIO_TypeDef* csPort;
    uint16_t csPin;

    
    GPIO_TypeDef* rstPort;
    uint16_t rstPin;
};

int rc522_init(struct rc522Stu *rc);
void rc522_antenna_set(struct rc522Stu *rc, uint8_t antennaStatus);
uint8_t rc522_card_write_block(struct rc522Stu *rc, uint8_t authMode, uint8_t addr, uint8_t *key, uint8_t *data, uint8_t *cardID);
uint8_t rc522_card_read_block(struct rc522Stu *rc, uint8_t authMode, uint8_t addr, uint8_t *key, uint8_t *data, uint8_t *cardID);

#endif
